package com.foftact.blockposition.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONPath;
import com.foftact.blockposition.BlockPosition;
import com.foftact.blockposition.mapper.BlockPositionMapper;
import com.foftact.blockposition.service.BlockPositionService;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.internal.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 板块成分股服务实现类
 */
@Service("blockPositionService")
public class BlockPositionServiceImpl implements BlockPositionService {
    private static final Logger logger = LoggerFactory.getLogger(BlockPositionServiceImpl.class);
    
    // 假设的API地址，实际使用时需要替换为真实的数据源
    private static final String API_URL = "http://example.com/api/blockposition";
    
    @Autowired
    private BlockPositionMapper blockPositionMapper;
    
    @Override
    @Transactional
    public int fetchAndSaveBlockPositionData(String blockCode) {
        logger.info("开始抓取板块成分股数据");
        int savedCount = 0;
        int deletedCount = 0;
        int page = 0;
        int pageSize = 20;

        do {
            try {
                page ++;
                // 1. 调用API获取数据
                String responseData = fetchBlockPositionDataFromEastMoney(blockCode, page, pageSize);

                // 2. 解析数据
                List<BlockPosition> blockPositions = parseData(responseData);
                if (blockPositions.size() <= 0) {
                    break;
                }
                // 3. 批量保存数据
                if (!blockPositions.isEmpty()) {
                    savedCount = blockPositionMapper.batchInsert(blockPositions);
                    logger.info("成功保存{}条板块成分股数据", savedCount);
                }
            } catch (Exception e) {
                logger.error("抓取板块成分股数据失败", e);
                throw new RuntimeException("抓取板块成分股数据失败", e);
            }

        } while (true);

        // 4. 删除超过1年的旧数据
        deletedCount += deleteOldData(365);
        logger.info("成功删除{}条超过1年的旧数据", deletedCount);

        return savedCount;
    }

    private String fetchBlockPositionDataFromEastMoney(String blockCode, int pn, int pz) throws Exception {
        logger.info("调用东方财富API获取板块成分股数据: {}", blockCode);

        try {
            // 构造API URL，支持分页获取所有数据
            String baseUrl = "https://push2.eastmoney.com/api/qt/clist/get";
            String params = "?pn=1&pz=20&np=1&fltt=1&invt=2&fields=f12,f13,f14,f1,f2,f4,f3,f152,f5,f6,f7,f15,f18,f16,f17,f10,f8,f9,f23&fid=f3&pn=$$pn$$&pz=$$pz$$&po=1&dect=1&ut=fa5fd1943c7b386f172d6893dbfba10b&wbp2u=|0|0|0|web";
            String fullUrl = baseUrl + params + "&fs=b:" + blockCode.toLowerCase() + "+f:!50";
            fullUrl = StringUtils.replace(fullUrl, "$$pn$$", String.valueOf(pn));
            fullUrl = StringUtils.replace(fullUrl, "$$pz$$", String.valueOf(pz));

            // 使用Jsoup发送GET请求，并设置Referer头
            Connection jsoupConn = Jsoup.connect(fullUrl).timeout(10000);
            jsoupConn.referrer("https://quote.eastmoney.com/center/gridlist.html#boards2-90." + StringUtils.upperCase(blockCode));
            jsoupConn.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");

            Connection.Response response = jsoupConn.execute();
            int responseCode = response.statusCode();

            if (responseCode == HttpURLConnection.HTTP_OK) {
                String jsonResponse = response.body();

                // 处理JSONP回调函数包装
                int start = jsonResponse.indexOf("(") + 1;
                int end = jsonResponse.lastIndexOf(")");
                if (start > 0 && end > start) {
                    jsonResponse = jsonResponse.substring(start, end);
                }

                return jsonResponse;
            } else {
                logger.warn("调用东方财富API失败，状态码: {}", responseCode);
                return StringUtils.EMPTY;
            }
        } catch (Exception e) {
            logger.error("调用东方财富API异常，使用模拟数据", e);
            return StringUtils.EMPTY;
        }
    }
    
    private String generateMockData() {
        // 生成模拟数据
        JSONArray mockData = new JSONArray();
        
        // 模拟数据样例
        String[] blockCodes = {"BK0001", "BK0002", "BK0003"};
        String[][] stockData = {
            {"000001", "平安银行", "1"},
            {"000002", "万科A", "1"},
            {"600036", "招商银行", "0"},
            {"600519", "贵州茅台", "0"},
            {"002594", "比亚迪", "1"}
        };
        
        for (String blockCode : blockCodes) {
            for (String[] stock : stockData) {
                JSONObject json = new JSONObject();
                json.put("marketCode", Integer.parseInt(stock[2]));
                json.put("code", stock[0]);
                json.put("name", stock[1]);
                json.put("blockCode", blockCode);
                json.put("dataSource", "MOCK_API");
                mockData.add(json);
            }
        }
        
        return mockData.toJSONString();
    }
    
    private List<BlockPosition> parseData(String responseData) {
        List<BlockPosition> result = new ArrayList<>();
        try {
            JSONArray dataArray = (JSONArray)JSONPath.eval(responseData, "$.data");
            Date now = new Date();
            
            for (Object obj : dataArray) {
                JSONObject json = (JSONObject) obj;
                BlockPosition blockPosition = new BlockPosition();
                
                blockPosition.setMarketCode(json.getInteger("marketCode"));
                blockPosition.setCode(json.getString("code"));
                blockPosition.setName(json.getString("name"));
                blockPosition.setBlockCode(json.getString("blockCode"));
                blockPosition.setDataSource(json.getString("dataSource"));
                blockPosition.setUpdateTime(now);
                blockPosition.setValid(true);
                
                result.add(blockPosition);
            }
        } catch (Exception e) {
            logger.error("解析板块成分股数据失败", e);
            throw new RuntimeException("解析板块成分股数据失败", e);
        }
        return result;
    }
    
    @Override
    public int saveBlockPosition(BlockPosition blockPosition) {
        if (blockPosition == null) {
            throw new IllegalArgumentException("板块成分股数据对象不能为空");
        }
        
        if (blockPosition.getUpdateTime() == null) {
            blockPosition.setUpdateTime(new Date());
        }
        
        if (blockPosition.getValid() == null) {
            blockPosition.setValid(true);
        }
        
        return blockPositionMapper.insertOrUpdate(blockPosition);
    }
    
    @Override
    @Transactional
    public int batchSaveBlockPosition(List<BlockPosition> blockPositions) {
        if (blockPositions == null || blockPositions.isEmpty()) {
            throw new IllegalArgumentException("板块成分股数据列表不能为空");
        }
        
        Date now = new Date();
        for (BlockPosition blockPosition : blockPositions) {
            if (blockPosition.getUpdateTime() == null) {
                blockPosition.setUpdateTime(now);
            }
            if (blockPosition.getValid() == null) {
                blockPosition.setValid(true);
            }
        }
        
        return blockPositionMapper.batchInsert(blockPositions);
    }
    
    @Override
    public BlockPosition getBlockPositionByMarketCodeAndCode(Integer marketCode, String code) {
        if (marketCode == null || code == null || code.trim().isEmpty()) {
            throw new IllegalArgumentException("市场码和股票代码不能为空");
        }
        return blockPositionMapper.selectByMarketCodeAndCode(marketCode, code);
    }
    
    @Override
    public List<BlockPosition> getBlockPositionsByBlockCode(String blockCode) {
        if (blockCode == null || blockCode.trim().isEmpty()) {
            throw new IllegalArgumentException("板块代码不能为空");
        }
        return blockPositionMapper.selectByBlockCode(blockCode);
    }
    
    @Override
    public List<BlockPosition> getAllBlockPositions() {
        return blockPositionMapper.selectAll();
    }
    
    @Override
    @Transactional
    public int deleteOldData(int days) {
        if (days <= 0) {
            throw new IllegalArgumentException("天数必须大于0");
        }
        return blockPositionMapper.deleteOldData(days);
    }
}